From 2746bed0cd7f4091b1a2a706765c64f849f77d1c Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Sat, 31 Mar 2007 16:35:02 +0100 Subject: [PATCH] xen x86: Fix double-fault handler stack overflow. 1. Shrink stack frame for __print_symbol() by introducing a lock and making the big arrays static. 2. Double the size of the double-fault stack. Also fix the show_stack_overflow function. Signed-off-by: Keir Fraser --- xen/arch/x86/traps.c | 2 +- xen/arch/x86/x86_32/traps.c | 5 ++--- xen/arch/x86/x86_64/traps.c | 8 ++++---- xen/common/symbols.c | 12 +++++++++--- xen/drivers/char/console.c | 8 +++++--- 5 files changed, 21 insertions(+), 14 deletions(-) diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index e1adce3b9e..99a332b874 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -291,7 +291,7 @@ void show_stack_overflow(unsigned long esp) unsigned long esp_top; unsigned long *stack, addr; - esp_top = (esp | (STACK_SIZE - 1)) - DEBUG_STACK_SIZE; + esp_top = (esp | (STACK_SIZE - 1)) - (DEBUG_STACK_SIZE - 1); /* Trigger overflow trace if %esp is within 512 bytes of the guard page. */ if ( ((unsigned long)(esp - esp_top) > 512) && diff --git a/xen/arch/x86/x86_32/traps.c b/xen/arch/x86/x86_32/traps.c index fe22212dd4..da8ca6bf5c 100644 --- a/xen/arch/x86/x86_32/traps.c +++ b/xen/arch/x86/x86_32/traps.c @@ -139,7 +139,7 @@ void show_page_walk(unsigned long addr) unmap_domain_page(l1t); } -#define DOUBLEFAULT_STACK_SIZE 1024 +#define DOUBLEFAULT_STACK_SIZE 2048 static struct tss_struct doublefault_tss; static unsigned char doublefault_stack[DOUBLEFAULT_STACK_SIZE]; @@ -268,8 +268,7 @@ void __init percpu_traps_init(void) tss->ds = __HYPERVISOR_DS; tss->es = __HYPERVISOR_DS; tss->ss = __HYPERVISOR_DS; - tss->esp = (unsigned long) - &doublefault_stack[DOUBLEFAULT_STACK_SIZE]; + tss->esp = (unsigned long)&doublefault_stack[DOUBLEFAULT_STACK_SIZE]; tss->__cr3 = __pa(idle_pg_table); tss->cs = __HYPERVISOR_CS; tss->eip = (unsigned long)do_double_fault; diff --git a/xen/arch/x86/x86_64/traps.c b/xen/arch/x86/x86_64/traps.c index dbdb47b65e..9e4502e934 100644 --- a/xen/arch/x86/x86_64/traps.c +++ b/xen/arch/x86/x86_64/traps.c @@ -270,18 +270,18 @@ void __init percpu_traps_init(void) stack_bottom = (char *)get_stack_bottom(); stack = (char *)((unsigned long)stack_bottom & ~(STACK_SIZE - 1)); - /* Double-fault handler has its own per-CPU 1kB stack. */ - init_tss[cpu].ist[0] = (unsigned long)&stack[1024]; + /* Double-fault handler has its own per-CPU 2kB stack. */ + init_tss[cpu].ist[0] = (unsigned long)&stack[2048]; /* NMI handler has its own per-CPU 1kB stack. */ - init_tss[cpu].ist[1] = (unsigned long)&stack[2048]; + init_tss[cpu].ist[1] = (unsigned long)&stack[3072]; /* * Trampoline for SYSCALL entry from long mode. */ /* Skip the NMI and DF stacks. */ - stack = &stack[2048]; + stack = &stack[3072]; wrmsr(MSR_LSTAR, (unsigned long)stack, ((unsigned long)stack>>32)); /* movq %rsp, saversp(%rip) */ diff --git a/xen/common/symbols.c b/xen/common/symbols.c index f4134b7ed5..60f3c335a6 100644 --- a/xen/common/symbols.c +++ b/xen/common/symbols.c @@ -16,6 +16,7 @@ #include #include #include +#include extern unsigned long symbols_addresses[]; extern unsigned long symbols_num_syms; @@ -140,12 +141,15 @@ const char *symbols_lookup(unsigned long addr, void __print_symbol(const char *fmt, unsigned long address) { const char *name; - unsigned long offset, size; - char namebuf[KSYM_NAME_LEN+1]; + unsigned long offset, size, flags; + static DEFINE_SPINLOCK(lock); + static char namebuf[KSYM_NAME_LEN+1]; #define BUFFER_SIZE sizeof("%s+%#lx/%#lx [%s]") + KSYM_NAME_LEN + \ 2*(BITS_PER_LONG*3/10) + 1 - char buffer[BUFFER_SIZE]; + static char buffer[BUFFER_SIZE]; + + spin_lock_irqsave(&lock, flags); name = symbols_lookup(address, &size, &offset, namebuf); @@ -155,4 +159,6 @@ void __print_symbol(const char *fmt, unsigned long address) snprintf(buffer, BUFFER_SIZE, "%s+%#lx/%#lx", name, offset, size); printk(fmt, buffer); + + spin_unlock_irqrestore(&lock, flags); } diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c index 87786f152f..d35a4c8809 100644 --- a/xen/drivers/char/console.c +++ b/xen/drivers/char/console.c @@ -858,19 +858,20 @@ __initcall(debugtrace_init); void panic(const char *fmt, ...) { va_list args; - char buf[128]; unsigned long flags; static DEFINE_SPINLOCK(lock); + static char buf[128]; debugtrace_dump(); + /* Protects buf[] and ensure multi-line message prints atomically. */ + spin_lock_irqsave(&lock, flags); + va_start(args, fmt); (void)vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); - /* Spit out multiline message in one go. */ console_start_sync(); - spin_lock_irqsave(&lock, flags); printk("\n****************************************\n"); printk("Panic on CPU %d:\n", smp_processor_id()); printk(buf); @@ -879,6 +880,7 @@ void panic(const char *fmt, ...) printk("Manual reset required ('noreboot' specified)\n"); else printk("Reboot in five seconds...\n"); + spin_unlock_irqrestore(&lock, flags); debugger_trap_immediate(); -- 2.30.2